#pragma once

/*
* kcp server manager
*/

#include <string>
#include "kcp_server.h"
#include "type.h"
#include "knet.h"
#include "thread_pool.hpp"
#include "asio/asio.hpp"

namespace KCP {
	class CKCPModule : public IKcpModule, asio::noncopyable {
	protected:
		CKCPModule();
		virtual ~CKCPModule();
		typedef std::vector<CKCPServer*> KCPServerArray;

	public:
		static CKCPModule& instance() {
			static CKCPModule gInstance;
			return gInstance;
		}

	public:
		// implement IKcpModule interface.
		virtual bool GNAPI Init();
		virtual bool GNAPI Run(int count);
		virtual IKServer* GNAPI Listen(const char* ip, unsigned short port, IKSessionFactory* factory);
		virtual bool GNAPI Connect(const char* ip, unsigned short port, IKSessionFactory* factory);

	public:
		// Create kcp server:
		// (ip,port) is remote address
		// factory is a session factory, which can create session.
		// listen denote server or client.
		CKCPServer* Create(const std::string& ip, uint16 port, IKSessionFactory* factory, bool listen);

		// Get main thread io_service.
		asio::io_service& GetIOService() {
			return m_ioService;
		}

		// Increase reference
		void IncRef() {
			m_ref++;
		}

		// decrease ref
		void DecRef() {
			m_ref--;
		}

	private:
		// stop kcp server.
		void        stop(CKCPServer* server);

	private:
		// main io_service.
		asio::io_service   m_ioService;
		KCPServerArray     m_array;
		CThreadPool        m_ioServicePool;
		int                m_ref{0};
	};
}